/**************************************************************************************************
**
**  文件名称:  diskdrv_USB.c
**  版权所有:  CopyRight @ Xiamen Yaxon NetWork CO.LTD. 2018
**  文件描述:  USB磁盘驱动管理模块
**  ===============================================================================================
**  创建信息:  | 2018-7-30 | LEON | 创建本模块
**  ===============================================================================================
**  修改信息:  单击此处添加....
**************************************************************************************************/
#include "fat_include.h"
#include "usbh_bsp.h"
#include "diskio.h"
#include "diskdrv_usb.h"

#ifdef USB_HOST

static volatile DSTATUS s_diskstatus = STA_NOINIT;

/**************************************************************************************************
**  函数名称:  USB_disk_initialize
**  功能描述:  初始化磁盘驱动器
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
DSTATUS USB_disk_initialize(void)
{
    if (HCD_IsDeviceConnected(USBH_BSP_GetOTGDev())) {  
        s_diskstatus &= ~STA_NOINIT;
    }

    return s_diskstatus;
}

/**************************************************************************************************
**  函数名称:  USB_disk_status
**  功能描述:  获取磁盘状态
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
DSTATUS USB_disk_status(void)
{
    return s_diskstatus;
}

/**************************************************************************************************
**  函数名称:  USB_disk_read
**  功能描述:  读取磁盘扇区内容
**  输入参数:  buff:   Pointer to the data buffer to store read data
**  输入参数:  sector: Start sector number (LBA)
**  输入参数:  count:  Sector count (1..255)
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
DRESULT USB_disk_read(BYTE *buff, DWORD sector, UINT count)
{
    BYTE status = USBH_MSC_OK;

    if (!count) return RES_PARERR;
    if (s_diskstatus & STA_NOINIT) return RES_NOTRDY;

    if (HCD_IsDeviceConnected(USBH_BSP_GetOTGDev())) {
        
        do {
            status = USBH_MSC_Read10(USBH_BSP_GetOTGDev(), buff, sector, 512 * count);
            
            USBH_MSC_HandleBOTXfer(USBH_BSP_GetOTGDev(), USBH_BSP_GetHostDev());

            if (!HCD_IsDeviceConnected(USBH_BSP_GetOTGDev())) {
                return RES_ERROR;
            }
        }
        while (status == USBH_MSC_BUSY);
    }

    if (status == USBH_MSC_OK) {
        return RES_OK;
    } else {
        return RES_ERROR;
    }
}

/**************************************************************************************************
**  函数名称:  USB_disk_write
**  功能描述:  写入磁盘扇区内容
**  输入参数:  buff:   Pointer to the data to be written
**  输入参数:  sector: Start sector number (LBA)
**  输入参数:  count:  Sector count (1..255)
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
DRESULT USB_disk_write(const BYTE *buff, DWORD sector, UINT count)
{
    BYTE status = USBH_MSC_OK;

    if (!count) return RES_PARERR;
    if (s_diskstatus & STA_NOINIT) return RES_NOTRDY;
    if (s_diskstatus & STA_PROTECT) return RES_WRPRT;

    if (HCD_IsDeviceConnected(USBH_BSP_GetOTGDev())) {
        
        do {
            status = USBH_MSC_Write10(USBH_BSP_GetOTGDev(), (BYTE*)buff, sector, 512 * count);
            
            USBH_MSC_HandleBOTXfer(USBH_BSP_GetOTGDev(), USBH_BSP_GetHostDev());

            if (!HCD_IsDeviceConnected(USBH_BSP_GetOTGDev())) {
                return RES_ERROR;
            }
        }
        while (status == USBH_MSC_BUSY);
    }

    if (status == USBH_MSC_OK) {
        return RES_OK;
    } else {
        return RES_ERROR;
    }
}

/**************************************************************************************************
**  函数名称:  USB_disk_ioctl
**  功能描述:  磁盘其他功能函数
**  输入参数:  ctrl:   Control code
**  输入参数:  buff:   Buffer to send/receive control data
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
DRESULT USB_disk_ioctl(BYTE ctrl, void *buff)
{
    DRESULT res;
    
    res = RES_ERROR;
    
    if (s_diskstatus & STA_NOINIT) {
        return RES_NOTRDY;
    }
    
    switch (ctrl)
    {
        case CTRL_SYNC:                                                        /* Make sure that no pending write process */
            res = RES_OK;
            break;

        case GET_SECTOR_COUNT:	                                               /* Get number of sectors on the disk (DWORD) */
            *(DWORD*)buff = (DWORD)USBH_MSC_Param.MSCapacity;
            res = RES_OK;
            break;

        case GET_SECTOR_SIZE:                                                  /* Get R/W sector size (WORD) */
            *(WORD*)buff = 512;
            res = RES_OK;
            break;

        case GET_BLOCK_SIZE:                                                   /* Get erase block size in unit of sector (DWORD) */
            *(DWORD*)buff = 512;
            res = RES_OK;
            break;

        default:
            res = RES_PARERR;
            break;
    }
    
    return res;
}

#else

DSTATUS USB_disk_initialize(void)
{
    return STA_NOINIT;
}

DSTATUS USB_disk_status(void)
{
    return STA_NOINIT;
}

DRESULT USB_disk_read(BYTE *buff, DWORD sector, UINT count)
{
    return RES_ERROR;
}

DRESULT USB_disk_write(const BYTE *buff, DWORD sector, UINT count)
{
    return RES_ERROR;
}

DRESULT USB_disk_ioctl(BYTE ctrl, void *buff)
{
    return RES_ERROR;
}

#endif


